package com.dy.yunying.biz.service.manage.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.dy.yunying.api.constant.Constant;
import com.dy.yunying.api.dto.AccountManageDTO;
import com.dy.yunying.api.dto.AccountProhibitDTO;
import com.dy.yunying.api.dto.AccountProhibitLogDTO;
import com.dy.yunying.api.entity.ProhibitInfoDO;
import com.dy.yunying.api.enums.AccountRegSrcEnum;
import com.dy.yunying.api.enums.ProhibitTypeEnum;
import com.dy.yunying.api.vo.AccountManageVO;
import com.dy.yunying.biz.dao.manage.AccountManageMapper;
import com.dy.yunying.biz.dao.manage.AccountProhibitMapper;
import com.dy.yunying.biz.service.manage.AccountManageService;
import com.dy.yunying.biz.service.manage.ProhibitLogService;
import com.dy.yunying.biz.utils.DateUtils;
import com.pig4cloud.pig.common.core.mybatis.Page;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author sunyq
 * @date 2022/8/19 13:31
 */
@Service
@Slf4j
public class AccountManageServiceImpl implements AccountManageService {

	@Autowired
	private StringRedisTemplate redisTemplate;

//	@Resource(name = "Redis1Template")
//	@Lazy
//	private RedisTemplate redisTemplate;
//
//	@Resource(name = "Redis2Template")
//	@Lazy
//	private RedisTemplate redisTemplateDubboCenter;

	@Autowired
	private AccountManageMapper accountManageMapper;

	@Autowired
	private AccountProhibitMapper accountProhibitMapper;

	@Autowired
	private ProhibitLogService prohibitLogService;

	@Resource(name = "clickhouseTemplate")
	private JdbcTemplate clickhouseTemplate;


	@Override
	public Page<AccountManageVO> selectWanUserPageByCondition(AccountManageDTO accountManageDTO) {
		if (StringUtils.isEmpty(accountManageDTO.getKpiValue())){
			accountManageDTO.setKpiValue("regtime");
		}
		if (StringUtils.isEmpty(accountManageDTO.getSort())){
			accountManageDTO.setSort("desc");
		}
		Page<AccountManageVO> accountManageVOPage = accountManageMapper.selectWanUserPageByCondition(accountManageDTO);
		return accountManageVOPage;
	}

	@Override
	public long selectTotalByCondition(AccountManageDTO accountManageDTO) {
		if (StringUtils.isEmpty(accountManageDTO.getKpiValue())){
			accountManageDTO.setKpiValue("regtime");
		}
		if (StringUtils.isEmpty(accountManageDTO.getSort())){
			accountManageDTO.setSort("desc");
		}
		return accountManageMapper.selectTotalByCondition(accountManageDTO);
	}

	@Override
	public R addAccountProhibit(AccountProhibitDTO dto) {
		try {
			AccountProhibitDTO wanProhibitDB = accountProhibitMapper.selectByUK(dto);
			if (Objects.isNull(wanProhibitDB)) {
				insert(dto);
			}else {
				update(dto);
			}
			return R.ok(0,"该账号已成功封禁");
		}catch (Exception e){
			log.error("该账号封禁失败,{}",e);
			return R.failed(11, "该账号封禁失败");
		}

	}

	@Override
	public R accountLeft(AccountProhibitDTO req) {
		try {
			AccountProhibitDTO accountProhibitDTO = new AccountProhibitDTO();
			accountProhibitDTO.setType(1);
			accountProhibitDTO.setStatus(2); // 解封
			accountProhibitDTO.setTime(0); // 永久
			accountProhibitDTO.setContent(req.getContent());

			Date now = DateUtils.getCurrentDate();
			Long userId = SecurityUtils.getUser().getId().longValue();

			accountProhibitDTO.setUpdateTime(now);
			accountProhibitDTO.setUpdator(userId);
			update(accountProhibitDTO);
			return R.ok("该账号解封成功");
		}catch (Exception e){
			log.error("该账号解封失败");
			return R.failed(11, "该账号解封失败");
		}
	}

	public void insert(AccountProhibitDTO dto) {
		Long userId = SecurityUtils.getUser().getId().longValue();
		Date now = DateUtils.getCurrentDate();
		dto.setUpdator(userId);
		dto.setUpdateTime(now);
		dto.setCreator(userId);
		dto.setCreateTime(now);
		accountProhibitMapper.insertSelective(dto);

		// 缓存封禁信息
		String redisKeyProhibit = Constant.REDIS_KEY_PROHIBIT_ + dto.getType() + "_" + dto.getContent();
		redisTemplate.opsForValue().set(redisKeyProhibit, JSON.toJSONString(dto));
		//刷新token,用于封建后退出
		refreshToken(dto);

		// 保存操作日志
		AccountProhibitLogDTO accountProhibitLogDTO = new AccountProhibitLogDTO();
		BeanUtils.copyProperties(dto, accountProhibitLogDTO);
		prohibitLogService.save(accountProhibitLogDTO);
	}

	private void refreshToken(AccountProhibitDTO dto) {
		log.info("封禁信息：{}",JSON.toJSONString(dto));
		if (StringUtils.isNotEmpty(dto.getContent())){
			LocalDate localDate = LocalDate.now().plusDays(-1);
			String format = localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
			Integer time = Integer.valueOf(format);
			//处理
			ProhibitTypeEnum prohibitTypeEnum = ProhibitTypeEnum.getProhibitTypeEnum(dto.getType());
			if (prohibitTypeEnum != null){
				switch (prohibitTypeEnum){
					case ACCOUNT:
						dealWithAccount(dto,time);
						break;
					case IP:
						String sqlIp = "SELECT usrname, gameid  FROM ch_dogame.user_login WHERE netip = ? and `day` > ? group BY usrname, gameid ";
						dealWithIP(dto,sqlIp,time);
						break;
					case IMEI:
						String sqlIMEI = "SELECT usrname, gameid  FROM ch_dogame.user_login WHERE (imei = ? or imei2 = ?) and `day` > ? group BY usrname, gameid ";
						dealWithIMEI(dto,sqlIMEI,time);
						break;
					case OAID:
						String sqlOAID = "SELECT usrname, gameid  FROM ch_dogame.user_login WHERE oaid = ? and `day` > ? group BY usrname, gameid ";
						dealWithIP(dto,sqlOAID,time);
						break;
					default:
						break;
				}
			}
		}
	}

	private void dealWithIMEI(AccountProhibitDTO dto, String sqlIMEI, Integer time) {
		List<ProhibitInfoDO> prohibitInfoDOS = clickhouseTemplate.queryForList(sqlIMEI, new Object[]{dto.getContent(),dto.getContent(),time}, ProhibitInfoDO.class);
		log.info("查询封禁游戏数据集合：{}", JSON.toJSONString(prohibitInfoDOS));
		if (CollectionUtils.isNotEmpty(prohibitInfoDOS)){
			for (ProhibitInfoDO prohibitInfoDO : prohibitInfoDOS) {
				delKey(prohibitInfoDO.getGameid(),prohibitInfoDO.getUsrname());
			}
		}
	}

	private void dealWithIP(AccountProhibitDTO dto, String sql, Integer time) {
		List<ProhibitInfoDO> prohibitInfoDOS = clickhouseTemplate.queryForList(sql, new Object[]{dto.getContent(),time}, ProhibitInfoDO.class);
		log.info("查询封禁游戏数据集合：{}", JSON.toJSONString(prohibitInfoDOS));
		if (CollectionUtils.isNotEmpty(prohibitInfoDOS)){
			for (ProhibitInfoDO prohibitInfoDO : prohibitInfoDOS) {
				delKey(prohibitInfoDO.getGameid(),prohibitInfoDO.getUsrname());
			}
		}
	}

	private void dealWithAccount(AccountProhibitDTO dto,Integer time) {


		String sql = "SELECT distinct(gameid) as gameId FROM user_login WHERE usrname = ? and `day` > ?";
		List<Integer> gameIds = clickhouseTemplate.queryForList(sql, new Object[]{dto.getContent(),time}, Integer.class);
		log.info("查询封禁游戏id集合：{}", JSON.toJSONString(gameIds));
		if (CollectionUtils.isNotEmpty(gameIds)){
			//删除sdk里面登录token
			for (Integer gameId : gameIds) {
				delKey(gameId,dto.getContent());
			}
		}
	}

	private void delKey(Integer gameId, String content) {
		String gameIdStr = gameId+"-";
		AccountRegSrcEnum[] values = AccountRegSrcEnum.values();
		for (AccountRegSrcEnum accountRegSrcEnum : values) {
			String key = Constant.REDIS_KEY_API_LOGIN_USER_+gameIdStr+content+"_"+accountRegSrcEnum.getType();
			log.info("封建账号删除key....{}",key);
			redisTemplate.delete(key);
		}
	}


	public void update(AccountProhibitDTO dto) {
		Long userId = SecurityUtils.getUser().getId().longValue();
		Date now = DateUtils.getCurrentDate();
		dto.setUpdator(userId);
		dto.setUpdateTime(now);
		dto.setType(1);
		accountProhibitMapper.updateByPrimaryKeySelective(dto);

		AccountProhibitDTO wanProhibitDB = accountProhibitMapper.selectByUK(dto);
		// 更新缓存
		Integer status = wanProhibitDB.getStatus();
		String redisKeyProhibit = Constant.REDIS_KEY_PROHIBIT_ + wanProhibitDB.getType() + "_" + wanProhibitDB.getContent();
		// 封禁
		if (status != null && 1 == status) {
			redisTemplate.opsForValue().set(redisKeyProhibit, JSON.toJSONString(wanProhibitDB));
			//刷新token,用于封建后退出
			refreshToken(dto);
		} else { // 解封
			redisTemplate.delete(redisKeyProhibit);
		}
		// 保存操作日志
		AccountProhibitLogDTO accountProhibitLogDTO = new AccountProhibitLogDTO();
		wanProhibitDB.setId(null);
		BeanUtils.copyProperties(wanProhibitDB, accountProhibitLogDTO);
		prohibitLogService.save(accountProhibitLogDTO);
	}

}
